package com.atguigu.security.controller;

import com.atguigu.security.config.MyPasswordEncoder;
import com.atguigu.security.config.MyUserDetailsService;
import com.sun.org.apache.xpath.internal.operations.And;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;

import javax.sql.DataSource;

/**
 * @author maomeng
 * @Configuration 声明当前类为配置类
 * @EnableWebSecurity 启用web环境下的权限控制功能
 * @create 2021-06-08- 15:32
 */
@Configuration
@EnableWebSecurity
public class WebAppSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private DataSource dataSource;

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    private MyPasswordEncoder myPasswordEncoder;

    /**
     * 实现账号密码的校验
     * @param builder
     * @throws Exception
     */
    @Override
    public void configure(AuthenticationManagerBuilder builder) throws Exception {
        //装配userDetailsService对象
        builder
        .userDetailsService(userDetailsService)
        .passwordEncoder(myPasswordEncoder);


        //基于内存的用户查询,没什么大用处
/*                //在内存中完成账号密码的检查
        .inMemoryAuthentication()
        // 指定账号
        .withUser("zhang")
        // 指定密码
        .password("123456")
        // 指定当前用户的角色
        .roles("ADMIN","学徒")
        .and()
        .withUser("mao")
        // 指定密码
        .password("123456")
        // 指定当前用户的角色
        .authorities("UPDATE","SAVE","DELETE");*/
    }

    /**
     * 权限控制的设置
     * @param security
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity security) throws Exception {

        // 创建一个用于持久化token的实现类对象
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        // 往这个对象里传入jdbcTemplet作为数据源
        tokenRepository.setDataSource(dataSource);

        //链式调用
        security.authorizeRequests()  // 对请求进行授权
            // 针对/index.jsp进行授权
            .antMatchers("/index.jsp")
            // 可以无条件访问
            .permitAll()
            // 针对/layui目录下所有资源进行授权
            .antMatchers("/layui/**")
            .permitAll()
            //针对路径设置访问要求
            .antMatchers("/level1/**")
            // 用户获取学徒的角色才能访问
            .hasRole("学徒")
            .antMatchers("/level2/**")
            // 用户获取学徒的角色才能访问
            .hasRole("大师")
            .antMatchers("/level3/**")
            // 用户获取学徒的角色才能访问
            .hasRole("宗师")
            // 链式调用的连接方法
            .and()
            // 对请求进行授权
            .authorizeRequests()
            // 对于任意请求
            .anyRequest()
            // 需要登录以后才能访问
            .authenticated()
            .and()
            // 以表单形式登录
            .formLogin()
            // 跳转到我们目标的登录页
            .loginPage("/index.jsp")
            // 指定提交登录表单的地址
            .loginProcessingUrl("/do/login.html")
            .permitAll()
            // 指定登录账号密码的请求参数名
            .usernameParameter("loginAcct")
            .passwordParameter("userPswd")
            .defaultSuccessUrl("/main.html")
            .and()
            .exceptionHandling()//访问被拒绝时前往的页面
            .accessDeniedPage("/to/no/auth/page.html")
            .and()
            .rememberMe()//开启记住用户的功能
            .tokenRepository(tokenRepository)
            ;
    }
}
